package com.geodroid.common.kernel.geos;



import java.util.ArrayList;

import com.geodroid.common.kernel.algos.AlgoElement;



public abstract class GeoElement extends ConstructionElement{
	
	/** parent algorithm */
	protected AlgoElement algoParent = null;
	//list of algorithms directly dependent
	private ArrayList<AlgoElement> algorithmList = new ArrayList<AlgoElement>();
	private boolean fixed = false;
	protected boolean highlighted = false;
	private boolean selected = false;
	
	private boolean selectionAllowed = false; 
	
	private boolean showTrimmedIntersectionLines = false;
	
	
	protected boolean isDefined = true;
	
	/**
	 * Makes object undefined, some objects lose their internally stored value when this is called
	 */
	public abstract void setUndefined();
	
	/**
	 * Returns false for undefined objects
	 * @return false when undefined
	 */
	public boolean isDefined(){
		return isDefined ;
	}
	
	public final void addAlgorithm(final AlgoElement algorithm) {
		if (!(getAlgorithmList().contains(algorithm))) {
			algorithmList.add(algorithm);
		}
	//	addToUpdateSets(algorithm);
	}
	
	
	
	/**
	 * 
	 */
	public GeoElement() {
		super();
		// TODO Auto-generated constructor stub
	}



	/**
	 * @return true if highlighted or selected
	 */
	final public boolean doHighlighting() {
		return (highlighted || selected)
				&& (!isFixed() || isSelectionAllowed());
	}
	/**
	 * 
	 * @return color of object for selection
	 */
	// Michael Borcherds 2008-04-02
//	public Color getSelColor() {
//		if (colFunction == null) {
//			return selColor;
//		}
//		return getRGBFromList(100);
//	}
	

	/**
	 * @return list of directly dependent algos
	 */
	final public ArrayList<AlgoElement> getAlgorithmList() {
		if (algorithmList == null) {
			algorithmList = new ArrayList<AlgoElement>();
		}
		return algorithmList;
	}


	/**
	 * @return algorithm responsible for computation of this object
	 */
	final public AlgoElement getParentAlgorithm() {
		return algoParent;
	}
	
	/**
	 * @return true if showing trimmed lines
	 */
	public boolean getShowTrimmedIntersectionLines() {
		return showTrimmedIntersectionLines ;
	}

	private boolean isChangeable() {
		return !fixed &&  isIndependent()  ;
	}
	
	/** @return true if this is fixed (moving & deleting forbidden) */
	public boolean isFixed() {
		return fixed;
	}

	@Override
	public boolean isIndependent() {
		return algoParent==null;
	}
	
	/**
	 * Returns whether this GeoElement can be moved in Euclidian View. Note:
	 * this is needed for texts and points on path
	 * 
	 * @return true for moveable objects
	 */
	public boolean isMoveable() {
		return isChangeable() || algoParent.hasOutputChangeable();
	}

	/**
	 * @return true if selection is allowed
	 */
	public boolean isSelectionAllowed() {
		return selectionAllowed ;
	}

	/**
	 * @param algorithm algorithm responsible for computation of this object
	 */
	public void setParentAlgorithm(final AlgoElement algorithm) {
		algoParent = algorithm;
	}
	

	@Override
	public void update() {
		// TODO Auto-generated method stub
	}

	/**
	 * Updates this object and all dependent ones. Note: no repainting is done
	 * afterwards! synchronized for animation
	 */
	public void updateCascade() {
		update();
		updateDependentObjects();
	}


	final private void updateDependentObjects() {
//		if ((correspondingCasCell != null) && isIndependent()) {
//			updateAlgoUpdateSetWith(correspondingCasCell);
//		} else if (algoUpdateSet != null) {
//			// update all algorithms in the algorithm set of this GeoElement
//			algoUpdateSet.updateAll();
//		}
		if (algorithmList.size()!=0){
			for(AlgoElement a : algorithmList)
	            a.update() ;
		}
	}

	public boolean isGeoConic() {
		// TODO Auto-generated method stub
		return false;
	}

	public boolean isGeoLine() {
		// TODO Auto-generated method stub
		return false;
	}







}
